import time
import random

import pygame
from pygame import K_0, K_t, K_q, K_a, K_ESCAPE, KEYDOWN


from gameclock import GameClock

hw_names = (
    'extremeslow',
    'slow' ,
    'normal', 
    'fast',
    'experimental',
)
hw_keys = range(K_0, K_0+len(hw_names))

def set_hw(hw):
    global hardware, max_ups, update_consumes, draw_consumes, sigma
    hardware = hw
    if hw == 0:
        update_consumes = 20
        draw_consumes = 20
        sigma = .75
    elif hw == 1:
        update_consumes = 15
        draw_consumes = 15
        sigma = .75
    elif hw == 2:
        update_consumes = 8
        draw_consumes = 4
        sigma = .1
    elif hw == 3:
        update_consumes = 4
        draw_consumes = 2
        sigma = .05
    elif hw == 4:
        update_consumes = 0
        draw_consumes = 0
        sigma = .01

speed = 100 / 1000.
debug = False
time_methods = ['pygame.time.get_ticks()', 'time.time()', 'time.clock()']
used_time_method = 0

class Car(object):
    def __init__(self, color, offset):
        self.position = 0.0
        self.prev_position = 0.0
        self.color = color
        self.offset = offset
        
    def update_game(self, real_dt, real_time, game_dt, game_time):
        self.prev_position = self.position
        self.position += speed * game_dt
        
    def update_real(self, real_dt, real_time):
        self.prev_position = self.position
        self.position += speed * real_dt
        
    def draw(self):
        pos = self.position
        pos %= screen.get_width()
        # screen.set_at((pos, self.offset), self.color)
        pygame.draw.rect(screen, self.color, pygame.Rect((pos, self.offset), (100, 20)))

class CarInt(Car):
    def draw(self, interpolation):
        pos = self.prev_position + (self.position - self.prev_position) * interpolation
        pos %= screen.get_width()
        # screen.set_at((pos, self.offset), self.color)
        pygame.draw.rect(screen, self.color, pygame.Rect((pos, self.offset), (100, 20)))

real_car = Car((155, 155, 255), 10)
real_car_int = CarInt((255, 255, 255), 40)

last_time = 0
def update(real_dt, game_time):
    global elapsed, nticks, nframes, last_time, running, time_methods, clock
#    real_dt = clock.last_update - last_time
    last_time = game_time
    real_car.update_real(real_dt, game_time)
    real_car_int.update_real(real_dt, game_time)
    
    elapsed += real_dt
    nticks += 1
    if elapsed >= 1000:
        pygame.display.set_caption('{0:d}:{1} | {2:0.1f} ups | {3:0.1f} fps | using: {4} | dilatation: {5}'.format(
            hardware, hw_names[hardware], nticks, nframes, time_methods[used_time_method], clock.dilatation))
        elapsed -= 1000
        nticks = 0
        nframes = 0
    w = int(random.gauss(update_consumes, sigma))
    if w: pygame.time.wait(w)

def draw(interpolation):
    global cars, screen, nframes
    nframes += 1
    screen.fill((0, 0, 0))
    real_car.draw()
    real_car_int.draw(interpolation)
    pygame.display.flip()
    w = int(random.gauss(draw_consumes, sigma))
    if w: pygame.time.wait(w)

last_ticks = 0
real = 0
app_start = time.time()
def get_ticks():
    global used_time_method, last_ticks, real, time_methods, app_start
    # make sure that all use same unit (here it is ms)
    if time_methods[used_time_method] == time_methods[0]:
        ticks = pygame.time.get_ticks()
    elif time_methods[used_time_method] == time_methods[1]:
        ticks = 1000 * (time.time() - app_start)
    elif time_methods[used_time_method] == time_methods[2]:
        ticks = 1000 * time.clock()
    dt = ticks - last_ticks
    # print 'now / dt:', ticks, dt
    last_ticks = ticks
    real += abs(dt) # make sure that the time goes on one direction (especially when chaning time query method)
    return real
    
def switch_time_method():
    global used_time_method, time_methods, last_ticks
    used_time_method += 1
    used_time_method %= len(time_methods)
    last_ticks = 0
    
def handle_events():
    global elapsed, nticks, nframes, last_time, running, time_methods, clock
    for e in pygame.event.get():
        if e.type == KEYDOWN:
            if e.key in hw_keys:
                set_hw(e.key-K_0)
            elif e.key == K_t:
                switch_time_method()
            elif e.key == K_q:
                clock.dilatation += 0.1
            elif e.key == K_a:
                clock.dilatation -= 0.1
            elif e.key == K_ESCAPE:
                running = False
    
pygame.init()
set_hw(2)
interval = 1000 / 30.
# clock = GameClock(pygame.time.get_ticks, update, interval, draw, 0)
clock = GameClock(get_ticks, update, interval, draw, 0)
elapsed = 0.
nticks = 0
nframes = 0

screen = pygame.display.set_mode((800, 600))

clock.tick()
running = True
while running:
    handle_events()
    clock.tick()
